As far as I have read into it, there are 2 ways:
- calculating your own log depth and writing it to gl_FragDepth, then a 16bit buffer already should give you really good results (But losing all possible hardware optimization like hyper-z and early-z rejection)
- 32bit float depth buffer with inverted range (possible with glDepthRangedNV from GL_NV_depth_buffer_float, also supported by AMD/ATI but not by Intel)
This seems to be the best overview about the tophic: Outerra: Maximizing Depth Buffer Range and Precision