However the problem is that while you can add external memory you can't make the processor "see it" as part of it's system so it is of limited use.
Natively, it couldn't.
However, if you implemented a small RTOS on top of the ATMega, with its own custom "scripting" engine, you could in theory set things up to utilize extra memory (anything from serial EEPROMS to SD cards, etc) in a transparent manner (similar to how old 8-bit operating systems, like OS-9 for the TRS-80 Color Computer, used the floppy drive to emulate a form of virtual memory).
Of course, in the end you would have all the overhead of the operating system, and less real memory to play with (and 2K on the 328 still might not be enough to implement the RTOS plus virtual memory, etc), and your scripting engine wouldn't run its code as fast as native code, of course.
But you would gain the ability to have larger programs (with bits swapped in and out as needed - modules, in a way), as well as multi-tasking (of a sort), and the possibility of an on-board command line/interpreter/programming environment.
I know there have been a few small RTOS systems created for the ATMega168/328 (some targeted for the Arduino); I've never looked at just how sophisticated they were, so while I know that some of the few I've seen support some of the above, I don't know if they support all of it.
Finally - while I can appreciate the "hack" value of implementing such a system on a microcontroller like the ATMega, in some way I also feel its a solution searching for problem: When you need that kind of sophistication, cramming the functionality into a small microcontroller may not be the best solution, considering the abundant availability of other solutions more suitable to the task (most of them are fairly inexpensive, and some at the top end of the range can even run full-size operating systems if that's a need).