Using the more functional style forEach method on the Array class avoids this problem.
This has been mentioned already but I'll expand on it here.
imageList.forEach( function ( item:MovieClip, index:int, list:Array) {
    // add your listener with closure here
})
Using this method, the function passed into the forEach defines a new scope each iteration. now you can add a closure inside this scope and it will remember each instance as you want.
On a related note:
Typing those 3 arguments the whole time is a pain so...
You can also make that less / more ugly with an adaptor function:
// just give me the item please
imageList.forEach ( itrAdpt( function ( image: ImageData ) {
    // add your listener with closure here
}))
// give me the item and it's index
imageList.forEach ( itrAdpt( function ( image: ImageData, index:int ) {
    // add your listener with closure here
}))
// give me the item, index and total list length
imageList.forEach ( itrAdpt( function ( image: ImageData, index:int, length:int ) {
    // add your listener with closure here
}))
where itrAdpt is a (possibly global) function defined something like:
public function itrAdpt(f: Function): Function
{
    var argAmount:int = f.length
    if (argAmount == 0)
    {
        return function (element:*, index:int, colection:*):* {
            return f(element)
        }
    }
    else if (argAmount == 1)
    {
        return function (element:*, index:int, colection:*):* {
            return f(element)
        }
    }
    else if (argAmount == 2)
    {
        return function (element:*, index:int, colection:*):* {
            return f(element, index)
        }
    }
    else if (argAmount == 3)
    {
        return function (element:*, index:int, colection:*):* {
            return f(element, index, colection.length)
        }
    }
    else
    {
        throw new Error("Don't know what to do with "+argAmount+"arguments. Supplied function should have between 1-3 arguments")
    }
}