Yo normalmente cargo las imágenes de forma asíncrona con alguna librería para evitarme el tener que usar WeakReferences y la caché y el liberar memoria consumida por los Bitmaps. Por ejemplo, Universal Image Loader te permite cargar las imágenes ocupándose de todo y además pudiendo decirle cuánto puede ocupar la caché de imágenes en memoria.
Probablemente en tu caso lo que ocurra es que aunque se reciclen las Views del ListView los Bitmaps asociados a ellas se mantengan en memoria por si se vuelven a utilizar. Además, ten en cuenta que una imagen que ocupa 30kb como jpg (quizás reescalada a un tamaño mayor) y como bitmap, es decir, sin ningún tipo de compresión, pueden ser varios megas. Yo he visto jpgs de 50kb pasar a ser bitmaps de 14MB en un Nexus 5 sin problemas.
Si no quieres tirar de librería yo intentaría llevar una caché de imágenes donde se almacenen las imágenes usadas recientemente y que al salir una de dicha caché se elimine totalmente de memoria.
Un saludo y suerte, las imágenes en Android pueden ser un problema bastante gordo.