For me, the Uno is nice for testing out bits of code on unknown hardware. If I break it, I can replace the IC easily and won't shed tears. But if I break the Mega doing something dumb, I have to buy a new one or pay almost as much for a new SMD chip as I did for the whole thing and attempt to rework it.
And the Uno is also nice for the fact that since it is using a DIP chip, you can prototpye with it and then build your project easily on a perfboard with just the 328P.
I came from using straight AVRs for my projects, and I had the Uno for a couple years that I got for a gift and never used it. I have come to like how easy it is to use and how the direct register stuff is mostly hidden. But, I will admit that the code it generates is huge compared to doing everything the raw way. Such are the sacrifices and the decision to make.
Arduino is really just C (and some C++) with really nice libraries written for you, so once you finish a project, it isn't terribly difficult to just port your code over to using raw gcc code. At the core of arduino, it using the raw C code anyway. So for digitalWrite for example, you can just go into the core code and look at how it was implemented and transfer the pieces over to your raw code. Learning C the Arduino way makes moving over to doing it another way a relatively small step.
In the end, Arduino is really, at it's base level, just an AVR development board. So there is also nothing stopping you from using the boards with just AVRStudio and writing code that way and just using the boards for all the support circuitry and shields. In fact I was doing just that when I first pulled my arduino out of the toolbox (maybe a month ago, actually) because I didn't see the beauty of the Arduino "package" at first.
It may not seem obvious to someone first starting out, but there is "Arduino, the hardware", and "Arduino, the software." And they are really separate from each other.
I do think someone needs to smack the person upside the head that decided to put in the offset headers, though. Definitely a marketing ploy to sell shields! There was no reason to do that other than to purposefully make it non-standard in a way that (mildly) forced people to buy shields. The marketing guys will say it is a "feature" to ensure you only plug in "blessed and tested" shields, but the marketing guys always say stuff like that. Obviously, many people have found ways around that, and of course they would.
With all that said, because the hardware and software are separate in the Arduino world, the code you develop on the Uno could easily just be compiled right on to the Mega by changing the "board" in the IDE if you start running out of room. If you have to make any chages at all to your code, it will be minor. But before changing out boards, I would experiment with trying to optimize code. There is more than one way to skin a cat, and some compile to smaller code than others. 32K is relatively huge in the microcontroller world. I have skimmed off a few K before just by changing the way I do things. Many people leave in Serial.begin for example when they aren't using the serial port in their final design. This adds in the entire serial library to the compiled code. By removing just that one line, you leave out a ton of code that you weren't using anyway.