Migrating activities is fairly trivial in most cases, since there are usually very few fields to work with.
Mapping Task/Event
Tasks have a status (done/not done), while events have a starting date/time and duration (or ending date/time). You should be able to identify most records from any reasonably designed system based on one of these two pieces of data being present. In the absence of both, other clues may exist, such as an activity type of "Email" (task) or a "Location" (event).
Most activities describe "who" they are associated with. This will be a lead or contact in salesforce.com. This may be laid out in the source from two separate tables, or a table of people with a certain "type" (usually named "lead" or "contact").
Many activities also describe "what" they are associated with. This is probably the most painful part of data mapping, because it could be any of a number of items, though the most usual cases are "account", "opportunity", and "case" (trouble ticket, etc), although custom objects may be possible.
Neither a "who" or a "what" preclude an activity being a task or event, although events usually include multiple "who" references, while tasks usually do not. The determining factor is almost exclusively a "status" value, or a "date/time" and "duration" value.
Mapping Relationships
Most systems use either unique IDs, or names, to reference related tables. Hopefully, it's a unique ID, which makes importing trivial. You should be able to use VLOOKUP (Excel) or queries (e.g. most database-driven systems) to attach a salesforce.com ID to an activity. Generally, you'll want three relationship pieces of information: the owner, the "who", and the "what." You can also map "Created" and "Last Modified" fields if you enable support for this feature by submitting a case to salesforce.com.
Special Considerations
Date and date/time values are in GMT in salesforce.com. You may need to convert your times from the other system's local time zone to GMT in order to upload the activities successfully. Also, dates must be in YYYY-MM-DD format, and date/time values must be in YYYY-MM-DDThh:mm:ss.SSSZ format, where T and Z are literal values, SSS is milliseconds (000 is fine), and hh is 00 through 23 (in Java's Date format parlance, "kk"). The data loader accepts several formats depending on locale, but this date and date/time format is considered the safest.
Archiving is automatic, periodic, and inevitable. You can't specify archived records, because they'll be automatically archived by the system when they meet certain criteria. Archiving doesn't reduce the activity's storage usage, but simply excludes these activities from reports and list views. The only special consideration is that there is no need to consider this behavior, because the system manages this flag for you. You can request a "further" archive period than what the defaults are, but this will significantly impact reporting speed for activities, so advise caution against expanding the window.
Created and Last Modified audit fields don't normally allow themselves to be inserted or updated. You can enable the feature to insert these values if they are important to the organization. You can only insert these values, not update, so if the data isn't mapped initially or is incorrect, the records should to be deleted before they are re-inserted.
You can load as many records as you want, assuming you don't run out of storage space or API calls for the day. See Setup > Company Profile > Company Information in regards to the number of API calls you get per day. Every 200 records in a batch is one API call. Each activity uses 2KB of database storage, regardless of content. You can find the current usage and maximum capacity under Setup > Data Management > Storage Usage. Advise that they load only relevant records, such as the last three years or so. Large, continuous imports may affect other integrations that also need API access until the 24 hour rolling window passes.
Loading activities requires that the related information (contacts, leads, accounts, opportunities, cases, etc) all exist first. You may need to load or map a ton of supplemental data in order to load these activities. In general, each additional table of data will require a minimum of an hour of mapping in most cases, assuming a proficiency in Excel. Of course, really small tables might only take a few minutes, while really large tables could take considerably longer.
Also, there may be some pre-configuration required before loading the data. For example, status values in salesforce.com should match incoming values. Data might need to be trimmed to fit inside the space provided (e.g. an event with 60,000 characters of description will lose half its text). You should try to identify these potential problems beforehand; a quick query will usually suffice if you load this data into a database like Access or MySQL.
Assuming there are no import errors, you can just spot-check the data when the import is done. If a few records look correct, then generally all the data will be correct; any errors would have been reporting during the import process. Conversely, if a few records are incorrect, most likely all records are incorrect. This usually comes in the flavor of a mis-matched lookup or incorrect translation of date or date/time values. This knowledge saves considerable time post-import.
You should try a trial import of 10-15 records before running the entire load. If the trial goes well, the entire import should go well. Retain the error files from the loads so that you can fix the problems specified, instead of having to wipe out all the data and starting clean.
Some fields are always read-only, most notably the auto-number data type. You can change the type to "text", import the data, then change them back to auto-number when you're done, if you need to.
Consider locking out all users except the user performing the import for the duration. You wouldn't want someone causing row locks or trying to synchronize their mobile device or Outlook while you're loading the data. While small imports are okay to leave the system open, the chances of Something Bad™ happening increase with the number of active users. While the system is multi-tenant, synchronization is generally best avoided during the middle of data loads, to be safe.
Perform large loads overnight or on the weekends. The system load is lower, so your performance will greatly increase, perhaps 50-100% or more. Also consider disabling validation rules, workflow rules, and triggers to boost your speed even more. Apply business logic to the records before importing to simulate the effects of the validation rules, workflow rules, and triggers. Perform the data load as a system administrator to avoid checks on sharing rules, etc, and you'll gain another significant boost to speed.
When loading in records, consider ordering them in reverse chronological order, with the newest records first. This gives immediate access to the most relevant information sooner, and then you can stagger in older records as you proceed. If you plan on splitting by date ranges, you should probably not choose arbitrary or calendar-spaced dates, but rather based on record counts, such as loading 20,000 records at a time each day. This will help manage API usage.