This optimization is done by the linker. If you don't reference UIPServer (EthernetServer) in the executinng code of your sketch, it's not copied to the arduino. The linker just copies the symbols (variables, functions and methods) that your sketch really depends on. It doesn't even copy private static initializing code if a class has only private constructors. You might have noticed the size-difference when using the Serial-object in comparism to not using it that shows up although the Serial-instance is declared implicitly. So there's no gain in using 'ifdefs' on methods you don't need besides some savings in compile-time.
the UIP_CONF_UDP define works, because the code left out is part of the gigantic uip_process-method that can be included by the linker as a whole - Adam Dunkels decided to optimize the code that no unavoidable function-calls are left using labels and gotos instead. While this might improve runtime-performance a bit it doesn't permit leaving out unused code at compiletime since all the code is reachable within the function (it depends on runtime-data whether it's being executed).
So one might leave out a bit of code in uip_process that is not mandatory to establish and maintain a tcp-connection (but you will loose all flexibility and maybe some reliability): there's the ICMP-stuff that is required for ping only (unfortunally no ifdef to leave that out easily, you'd have to modify uip.c). You might decide to use fixed (in the sense of defined as constant in the code) ip and ethernet-address (UIP_FIXEDADDR and UIP_FIXEDETHADDR, I havn't tested whether the UIPClient/Server code compiles or runs with that). Then you might leave out checksums (allways return 0 or 0xffff, you'd have to check which works) by replacing the checksum-code in UIPEthernet.cpp. And you might even use predefined const arp-tables and leave out most of the arp-code (also no existing ifdefs for that, you'd have to write alternative implementations for arp_in() and arp_out()).
If your sketch is a server you might set UIP_ACTIVE_OPEN to 0 which leaves out the code for outgoing connections from uip_process().
And finally you don't need the Server for a client-only sketch. Just declare an Instance of EthernetClient, run Ethernet.begin() and you are ready to execute client.connect().
(repace Ethernet.begin(mac) wich Ethernet.begin(mac,ip) - otherwise it requires dhcp and thus udp...)